#include "Mcat/plane.h"
#include "stdio.h"
#include "timer.h"
#include "math.h"
#include "string.h"
#include "conio.h"
#include "system.h"

#ifndef win_width
#define win_width 20
#endif

#ifndef win_height
#define win_height 25
#endif

typedef struct splane
{
	int location_x;
	int location_y;
	struct splane *next;
	int type;	//1: smallPlane   2: planeShot
}SPlane;

static int speed=4;
static int speed_count=0;
static int scores=0;

static int randS=8;
static uint32_t bodySize = 0;
static int plane_count=0;
static uint32_t startMem = 0xf00000;

static int plane_x=win_width/2-1;
static int plane_y=win_height-2;
static int plane_map[win_height][win_width];


SPlane *head;
SPlane *nowP;

int Rand()
{
	randS=(randS*plane_count*plane_count+2)%win_width;
	return randS;
}

SPlane* plane_rand_created(){
	SPlane *s;
	int p = startMem + bodySize*sizeof(SPlane);
	if (p>=0xffffff)
	{
		p = startMem;
	}
	s = (SPlane*)p;
	bodySize++;
	s->next = NULL;
	s->type=1;
	return s;
}
void create_plane(){
	if(speed_count!=speed){
		speed_count++;
		return;
	}
	speed_count=0;
	SPlane *s;
	int p = startMem + bodySize*sizeof(SPlane);
	if (p>=0xffffff)
	{
		p = startMem;
	}
	s = (SPlane*)p;
	bodySize++;
	s->next = NULL;
	s->type=1;
	s->location_x=Rand();
	s->location_y=0;
	nowP->next=s;
	nowP=s;
	plane_count++;
}
void create_plane_shot(){
	SPlane *s;
	int p = startMem + bodySize*sizeof(SPlane);
	if (p>=0xffffff)
	{
		p = startMem;
	}
	s = (SPlane*)p;
	bodySize++;
	s->next = NULL;
	s->type=2;
	s->location_x=plane_x+1;
	s->location_y=plane_y+1;
	nowP->next=s;
	plane_count++;
	nowP=s;
}
void plane_init()
{
	int i=0,j=0;
	for(;i<win_height;i++){
		for(;j<win_width;j++){
			plane_map[i][j]=0;
		}
	}
	// init the plane
	plane_map[plane_y][plane_x+1]=1;
	plane_map[plane_y+1][plane_x]=1;
	plane_map[plane_y+1][plane_x+1]=1;
	plane_map[plane_y+1][plane_x+2]=1;
	head=plane_rand_created();
	nowP=head;
}

void plane_map_printf()
{
	console_clear();
	int i=0,j=0;
	for(i=0;i<win_height;i++){	
		for(j=0;j<win_width;j++){
			if(plane_map[i][j]>=1)
				printf("*");
			else
				printf(" ");
		}
		printf("|\n");
	}
	printf("a : left; w : up; d : right; s : down;");
	for(i=0;i<win_width;i++)
		printf("_");
}
void resetPlanemap(){
	SPlane *p;
	p=head->next;
	int i,j;
	for(i=0;i<win_height;i++){
		for(j=0;j<win_width;j++){
			plane_map[i][j]=0;
		}
	}
	i=0;
	while(i++<plane_count){
		if(p->type==1){
			plane_map[p->location_y][p->location_x]=1;
			plane_map[p->location_y][p->location_x+1]=1;
			plane_map[p->location_y+1][p->location_x]=1;
			plane_map[p->location_y+1][p->location_x+1]=1;
		}else if(p->type==2){
			plane_map[p->location_y][p->location_x]=2;
		}
		p=p->next;
	}
	// set the self plane code
	plane_map[plane_y][plane_x+1]=1;
	plane_map[plane_y+1][plane_x]=1;
	plane_map[plane_y+1][plane_x+1]=1;
	plane_map[plane_y+1][plane_x+2]=1;
}


// srand the splane
void createdPlane(){
	SPlane *p1;
	p1=plane_rand_created();
	p1->location_x=Rand();
	nowP->next=p1;
	nowP=p1;
}

//check the map
int plane_check(){
	// check the small plane
	if(plane_map[plane_y-1][plane_x]==1||plane_map[plane_y-1][plane_x+2]==1||plane_map[plane_y-1][plane_x+3]==1){
		return 0;
	}
	//check the plane shot
	SPlane *p,*p1;
	p1=head;
	p=p1->next;
	int count=0;
	while(count++<=plane_count){
		if(p->type==1){
			if(plane_map[p->location_y+2][p->location_x]==2||plane_map[p->location_y+2][p->location_x+1]==2||p->location_y>=win_height-2)
			{
				p->type=3;
				scores++;
			}
			else
			{
				p->location_y++;
				p1=p;
				
			}
		}else if(p->type==2){
			p->location_y--;
			p1=p;
			// if(plane_map[p->location_y-1][p->location_x]==1||p->location_y<=0)
			// {
			// 	p1->next=p->next;
			// 	p=p1->next;
			// 	plane_count--;
			// }
			// else
			// {
			// 	p->location_y--;
			// 	p1=p;
			// 	p=p->next;
			// }
		}
		p=p->next;
	}
	return 1;
}

void plane_up(){
	if(plane_y<=0)
		return;
	plane_map[plane_y-1][plane_x+1]=1;

	plane_map[plane_y][plane_x]=1;
	plane_map[plane_y][plane_x+2]=1;

	plane_map[plane_y+1][plane_x]=0;
	plane_map[plane_y+1][plane_x+1]=0;
	plane_map[plane_y+1][plane_x+2]=0;
	plane_y--;
}

void plane_down(){
	if(plane_y>=win_height-2)
		return;
	plane_map[plane_y+2][plane_x]=1;
	plane_map[plane_y+2][plane_x+1]=1;
	plane_map[plane_y+2][plane_x+2]=1;

	plane_map[plane_y+1][plane_x]=0;
	plane_map[plane_y+1][plane_x+2]=0;

	plane_map[plane_y+1][plane_x+1]=1;
	plane_map[plane_y][plane_x+1]=0;

	plane_y++;
}

void plane_left()
{
	if(plane_x<=0)
		return;
	plane_map[plane_y+1][plane_x-1]=1;
	plane_map[plane_y+1][plane_x+2]=0;

	plane_map[plane_y][plane_x+1]=0;
	plane_map[plane_y][plane_x]=1;

	plane_x--;
}

void plane_right(){
	if((plane_x+2)>=win_width)
		return;
	plane_map[plane_y+1][plane_x]=0;
	plane_map[plane_y+1][plane_x+3]=1;

	plane_map[plane_y][plane_x+2]=1;
	plane_map[plane_y][plane_x+1]=0;

	plane_x++;
}

int plane_one_step_run(int keyDown){
	int result=0;
	switch(keyDown){
		case 75:{
			plane_left();
			break;
		}
		case 72:{
			plane_up();	
			break;
		}
		case 77:{
			plane_right();
			break;
		}
		case 80:{
			plane_down();
			break;
		}
		case 1:{
			return 0;
		}
	};

	create_plane();
	create_plane_shot();
	result=plane_check();
	resetPlanemap();
	plane_map_printf();
	printf("%d\n", scores);
	return 1;
}



void plane_run()
{
	int keyDown=0;
	plane_init();
	plane_map_printf();
	while(1)
	{
		keyDown=getchInStep(6000000);
		plane_one_step_run(keyDown);
		if(!plane_one_step_run(keyDown)){
			console_clear();
			printf("Game Over\n");
			break;
		}
	}
}